"""
知识库管理服务
"""
from typing import List, Optional, Dict, Any, Tuple
from src.llm.hiagent_app.utils.api_client import HiAgentAPIClient
from src.llm.hiagent_app.models.hiagent_models import KnowledgeBase, ListOption, ProcessRuleFileType
from src.llm.hiagent_app.config.hiagent_config import HiAgentConfig


class KnowledgeService:
    """知识库服务类"""
    
    def __init__(self, api_client: Optional[HiAgentAPIClient] = None):
        self.api_client = api_client or HiAgentAPIClient()
    
    def create_dataset(
        self,
        name: str,
        description: str,
        workspace_id: str,
        icon: Optional[str] = None,
        indexing_technique: Optional[int] = None,
        retrieval_search_method: Optional[int] = None,
        models: Optional[Dict[str, Any]] = None,
        api_config: Optional[Dict[str, Any]] = None,
        labels: Optional[List[Dict[str, Any]]] = None,
        directory_id: Optional[str] = None
    ) -> Optional[str]:
        """创建知识库"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "Name": name,
            "Description": description,
            "SpaceType": 1,  # 1=个人空间
            "WorkspaceID": workspace_id
        }
        
        if icon:
            body["Icon"] = icon

        if indexing_technique is not None:
            body["IndexingTechnique"] = indexing_technique

        if retrieval_search_method is not None:
            body["RetrievalSearchMethod"] = retrieval_search_method
        
        if models:
            body["Models"] = models
        
        if api_config:
            body["APIConfig"] = api_config
        
        if labels:
            body["Labels"] = labels
        
        if directory_id:
            body["DirectoryID"] = directory_id
        
        try:
            response = self.api_client.make_request("CreateDataset", body)
            return response.get("Id")
        except Exception as e:
            print(f"Error creating dataset: {e}")
            return None
    
    def list_datasets(
        self,
        workspace_id: str,
        page_number: int = 1,
        page_size: int = 10,
        keyword: Optional[str] = None,
        labels: Optional[List[str]] = None,
        sort_field: Optional[str] = None,
        sort_order: Optional[str] = None
    ) -> Tuple[List[KnowledgeBase], int]:
        """获取知识库列表"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "PageNumber": page_number,
            "PageSize": page_size,
            "WorkspaceID": workspace_id
        }
        
        # 设置筛选条件
        filter_dict = {}
        if keyword:
            filter_dict["Keyword"] = keyword
        if labels:
            filter_dict["Labels"] = labels
        
        if filter_dict:
            body["Filter"] = filter_dict
        
        # 设置排序
        if sort_field and sort_order:
            body["Sort"] = [{
                "Field": sort_field,
                "Order": sort_order
            }]
        
        try:
            response = self.api_client.make_request("ListDatasets", body)
            
            datasets = []
            for item in response.get("Items", []):
                datasets.append(KnowledgeBase(
                    kb_id=item.get("Id", ""),
                    name=item.get("Name", ""),
                    description=item.get("Description", ""),
                    workspace_id=item.get("WorkspaceID", ""),
                    icon=item.get("Icon"),
                    created_time=item.get("CreatedAt"),
                    updated_time=item.get("UpdatedAt"),
                    document_count=item.get("DocumentCount"),
                    size=item.get("Size"),
                    status=item.get("Status")
                ))
            
            total = response.get("Total", 0)
            return datasets, total
        except Exception:
            return [], 0
    
    def get_dataset(self, dataset_id: str, workspace_id: str) -> Optional[KnowledgeBase]:
        """获取知识库详情"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "Id": dataset_id,
            "WorkspaceID": workspace_id
        }
        
        try:
            response = self.api_client.make_request("GetDataset", body)
            
            if not response:
                return None
            
            return KnowledgeBase(
                kb_id=response.get("Id", ""),
                name=response.get("Name", ""),
                description=response.get("Description", ""),
                workspace_id=response.get("WorkspaceID", ""),
                icon=response.get("Icon"),
                created_time=response.get("CreatedAt"),
                updated_time=response.get("UpdatedAt"),
                document_count=response.get("DocumentCount"),
                size=response.get("Size"),
                status=response.get("Status")
            )
        except Exception:
            return None
    
    def update_dataset(
        self,
        dataset_id: str,
        workspace_id: str,
        name: Optional[str] = None,
        description: Optional[str] = None,
        icon: Optional[str] = None
    ) -> bool:
        """更新知识库"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "Id": dataset_id,
            "WorkspaceID": workspace_id
        }
        
        if name is not None:
            body["Name"] = name
        
        if description is not None:
            body["Description"] = description
        
        if icon is not None:
            body["Icon"] = icon
        
        try:
            self.api_client.make_request("UpdateDataset", body)
            return True
        except Exception:
            return False
    
    def delete_dataset(self, dataset_id: str, workspace_id: str) -> bool:
        """删除知识库"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "Id": dataset_id,
            "WorkspaceID": workspace_id
        }
        
        try:
            self.api_client.make_request("DeleteDataset", body)
            return True
        except Exception:
            return False
    
    def validate_dataset_exist(self, dataset_id: str, workspace_id: Optional[str] = None) -> bool:
        """验证知识库是否存在"""
        body = {
            "Id": dataset_id
        }
        
        if workspace_id:
            body["WorkspaceID"] = workspace_id
        
        try:
            response = self.api_client.make_request("ValidateDatasetExist", body)
            return response.get("Exist", False)
        except Exception:
            return False
    
    def create_document(
        self,
        dataset_id: str,
        name: str,
        workspace_id: str,
        content: Optional[str] = None,
        file_url: Optional[str] = None,
        labels: Optional[List[str]] = None
    ) -> Optional[str]:
        """
        创建文档

        Args:
            dataset_id: 知识库ID
            name: 文档名称
            workspace_id: 工作空间ID (必填)
            content: 文档内容（用于文本内容）
            file_url: 文件URL（HiAgent上传后的ObsUrl）
            labels: 标签列表

        Returns:
            文档ID，失败返回None
        """
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        # 1. 检测文件类型（从文件名提取扩展名）
        file_ext = name.split('.')[-1].lower() if '.' in name else 'txt'

        # 2. 根据文件扩展名确定文档类型和 ProcessRuleFileType
        # 根据 HiAgent API 规范：
        # - MD文件用 MarkdownDocuments (ProcessRuleFileType=3)
        # - JSON文件用 JsonDocument (ProcessRuleFileType=4)
        # - 结构化文件用 StructureDocument (ProcessRuleFileType=1)
        # - 其他文件用 NormalDocuments (ProcessRuleFileType=0)
        if file_ext in ['md', 'markdown']:
            doc_type = 3  # Markdown
            process_rule_file_type = ProcessRuleFileType.MD.value
        elif file_ext in ['json', 'jsonl']:
            doc_type = 2  # Json
            process_rule_file_type = ProcessRuleFileType.JSON.value
        elif file_ext in ['xls', 'xlsx', 'csv']:
            doc_type = 1  # Structure
            process_rule_file_type = ProcessRuleFileType.XLSX.value
        else:
            doc_type = 0  # Normal (txt, pdf, docx, etc.)
            process_rule_file_type = ProcessRuleFileType.from_extension(file_ext)

        # 3. 构造请求体基础部分
        body = {
            "DatasetId": dataset_id,
            "WorkspaceID": workspace_id,
            "ProcessRuleFileType": process_rule_file_type
        }

        # 4. 根据文档类型构造文档对象和选择正确的字段
        if file_url or content:
            if doc_type == 3:
                # Markdown 文档：使用 MarkdownDocuments 字段
                # Markdown必须使用手动配置，不能使用ProcessRule=0
                # 注意：Markdown文档也需要使用ObsUrl字段（不是Url）
                doc = {
                    "Filename": name,
                    "ObsUrl": file_url,  # Markdown文档使用 ObsUrl（不是Url）
                    "Type": 0,  # Normal类型
                    "ProcessRule": 1,  # 1=分句索引（Markdown必需）
                    "ProcessRuleDelimiter": "\n",  # 分隔符（ProcessRule=1时必需）
                    "ProcessRuleChunkSize": 1000,  # 文档分段字符数
                    "ReserveTitle": True  # 保留标题
                }
                body["MarkdownDocuments"] = [doc]

            elif doc_type == 2:
                # JSON 文档：使用 JsonDocument 字段（单个对象，不是数组）
                doc = {
                    "Filename": name,
                    "Url": file_url  # JSON文档使用 Url 而不是 ObsUrl
                }
                body["JsonDocument"] = doc

            elif doc_type == 1:
                # 结构化文档：使用 StructureDocument 字段（单个对象，不是数组）
                doc = {
                    "Filename": name,
                    "Url": file_url  # 结构化文档使用 Url 而不是 ObsUrl
                }
                body["StructureDocument"] = doc

            else:
                # 普通文档：使用 NormalDocuments 字段
                # 使用自动分割模式（ProcessRule=0）让系统自动处理
                doc = {
                    "Filename": name,
                    "Type": 0,  # 固定为 Normal (0)
                    "ProcessRule": 0,  # 0=自动分割（推荐，系统自动选择最佳方式）
                    "ObsUrl": file_url  # 必须使用 ObsUrl，不能用 Url
                }
                body["NormalDocuments"] = [doc]

        # 5. 添加标签
        if labels:
            # 转换为 DatasetLabel 格式
            dataset_labels = []
            for label in labels:
                dataset_labels.append({"Value": label})
            body["DocumentLabels"] = dataset_labels

        print(f"[KnowledgeService] CreateDocument request body: {body}")

        try:
            response = self.api_client.make_request("CreateDocument", body)
            # 响应返回的是 Ids 列表
            ids = response.get("Ids", [])
            if ids:
                return ids[0]  # 返回第一个文档ID
            return None
        except Exception as e:
            print(f"[KnowledgeService] CreateDocument failed: {str(e)}")
            return None
    
    def list_documents(
        self,
        dataset_id: str,
        workspace_id: str,
        page_number: int = 1,
        page_size: int = 10,
        keyword: Optional[str] = None
    ) -> Tuple[List[Dict[str, Any]], int]:
        """
        获取文档列表

        Args:
            dataset_id: 知识库ID
            workspace_id: 工作空间ID (必填)
            page_number: 页码（从1开始）
            page_size: 每页数量
            keyword: 关键词搜索（文件名过滤）

        Returns:
            (文档列表, 总数)
        """
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        # 按照HiAgent原生API规范构造请求
        body = {
            "WorkspaceID": workspace_id,
            "DatasetId": dataset_id,
            "PageNumber": page_number,
            "PageSize": page_size,
            "Top": {                      # 分页参数（必需）
                "PageNumber": page_number,
                "PageSize": page_size
            }
        }

        # 如果有关键词，添加Filter过滤条件
        if keyword:
            body["Filter"] = {
                "Filename": keyword  # 按文件名过滤
            }

        try:
            response = self.api_client.make_request("ListDocuments", body)

            documents = response.get("Items", [])
            total = response.get("Total", 0)

            return documents, total
        except Exception as e:
            print(f"[KnowledgeService] ListDocuments failed: {str(e)}")
            return [], 0
    
    def delete_document(
        self,
        document_id: str,
        workspace_id: str,
        dataset_id: Optional[str] = None
    ) -> bool:
        """
        删除文档

        Args:
            document_id: 文档ID
            workspace_id: 工作空间ID (必填)
            dataset_id: 知识库ID（可选，根据API可能需要）

        Returns:
            是否删除成功
        """
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        # 按照HiAgent API规范构造请求
        # 注意：文档中DeleteDocument的请求参数定义不完整
        # 根据其他API（GetDocument等）的模式，应该需要这些参数
        body = {
            "WorkspaceID": workspace_id,
            "Id": document_id,
            "Top": {  # 可能需要的分页参数
                "PageNumber": 1,
                "PageSize": 1
            }
        }

        # 如果提供了dataset_id，也加入请求
        if dataset_id:
            body["DatasetId"] = dataset_id

        try:
            self.api_client.make_request("DeleteDocument", body)
            return True
        except Exception as e:
            print(f"[KnowledgeService] DeleteDocument failed: {str(e)}")
            return False
    
    def query_knowledge(
        self,
        dataset_id: str,
        query: str,
        workspace_id: str,
        top_k: int = 5,
        score_threshold: Optional[float] = None
    ) -> List[Dict[str, Any]]:
        """
        知识库检索

        Args:
            dataset_id: 知识库ID
            query: 查询关键词
            workspace_id: 工作空间ID (必填)
            top_k: 返回结果数量
            score_threshold: 相似度阈值

        Returns:
            检索结果列表，每个结果包含：
            - DatasetID: 知识库ID
            - DatasetName: 知识库名称
            - DocumentID: 文档ID
            - DocumentName: 文档名称
            - SegmentID: 片段ID
            - Content: 内容
            - Score: 相似度分数
            - 等其他字段
        """
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        # 按照HiAgent原生API规范构造请求
        body = {
            "WorkspaceID": workspace_id,
            "DatasetIds": [dataset_id],  # 注意：DatasetIds是复数，且为list类型
            "Keywords": [query],          # 注意：Keywords是复数，且为list类型
            "TopK": top_k,
            "Top": {                      # 分页参数（必需）
                "PageNumber": 1,
                "PageSize": 20
            }
        }

        if score_threshold is not None:
            body["ScoreThreshold"] = score_threshold

        try:
            response = self.api_client.make_request("Query", body)
            return response.get("Results", [])
        except Exception as e:
            print(f"[KnowledgeService] Query failed: {str(e)}")
            return []
    
    def create_qa_dataset(
        self,
        name: str,
        description: str,
        workspace_id: str,
        icon: Optional[str] = None,
        directory_id: Optional[str] = None
    ) -> Optional[str]:
        """创建问答库"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "Name": name,
            "Description": description,
            "WorkspaceID": workspace_id
        }
        
        if icon:
            body["Icon"] = icon
        
        if directory_id:
            body["DirectoryID"] = directory_id
        
        try:
            response = self.api_client.make_request("CreateQADataset", body)
            return response.get("Id")
        except Exception:
            return None
    
    def list_qa_datasets(
        self,
        workspace_id: str,
        page_number: int = 1,
        page_size: int = 10
    ) -> Tuple[List[Dict[str, Any]], int]:
        """获取问答库列表"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "PageNumber": page_number,
            "PageSize": page_size,
            "WorkspaceID": workspace_id
        }
        
        try:
            response = self.api_client.make_request("ListQADatasets", body)
            
            datasets = response.get("Items", [])
            total = response.get("Total", 0)
            
            return datasets, total
        except Exception:
            return [], 0
    
    def create_term_dataset(
        self,
        name: str,
        description: str,
        workspace_id: str,
        icon: Optional[str] = None,
        directory_id: Optional[str] = None
    ) -> Optional[str]:
        """创建术语库"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "Name": name,
            "Description": description,
            "WorkspaceID": workspace_id
        }
        
        if icon:
            body["Icon"] = icon
        
        if directory_id:
            body["DirectoryID"] = directory_id
        
        try:
            response = self.api_client.make_request("CreateTermDataset", body)
            return response.get("Id")
        except Exception:
            return None
    
    def list_term_datasets(
        self,
        workspace_id: str,
        page_number: int = 1,
        page_size: int = 10
    ) -> Tuple[List[Dict[str, Any]], int]:
        """获取术语库列表"""
        # 验证workspace_id必填
        if not workspace_id:
            raise ValueError("workspace_id is required and cannot be None or empty")

        body = {
            "PageNumber": page_number,
            "PageSize": page_size,
            "WorkspaceID": workspace_id
        }
        
        try:
            response = self.api_client.make_request("ListTermDatasets", body)
            
            datasets = response.get("Items", [])
            total = response.get("Total", 0)
            
            return datasets, total
        except Exception:
            return [], 0